<?php
	namespace ampleharvest\task\process_data;
	use\ampleharvest\code\cRestServices;
	use\ampleharvest\code\cRestConnector;
	use\ampleharvest\code\cConfig;
	use\ampleharvest\code;

	require_once dirname(dirname(dirname(dirname(__FILE__)))) . "/config/cConfig.php";
	require_once dirname(dirname(dirname(dirname(__FILE__)))) . "/config/cRestServices.php";
	require_once dirname(dirname(dirname(dirname(__FILE__)))) . "/classes/cRestConnector.php";
	require_once dirname(dirname(dirname(dirname(__FILE__)))) . "/abstract_classes/abs_Task.php";
	require_once dirname(dirname(dirname(dirname(__FILE__)))) . "/classes/cThread.php";
	require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/validation/json/cJsonValidator.php';
	require_once dirname(dirname(dirname(dirname(__FILE__)))) . '/classes/cStomp.php';

	$arr_Params = array("id::");

	$arr_Options = getopt("c::", $arr_Params);
	/**
	 * @brief This Task Handles pulling ids of objects off a Queue and pulling out important information then putting the ids in a queue to be Indexed
	 *
	 * - Revision History
	 *  - 0.1
	 * 	 - <b>Date</b>: 02 SEP 2011
	 * 	 - <b>Author</b>: Randy Blancett
	 * 	  - Initial Version
										
	 * @author Randy Blancett
	 * @version 0.1
	 * @ingroup code
																										
	 */
	class process_Data_Queue extends \abs_Task
	{
		const C_STR_NAME = "process_Data_Queue";
		const C_INT_THREADS = 5;
		const C_INT_PULL_THREADS = 5;

		protected $m_arr_Threads = null;
		protected $arr_Options = null;

		protected $m_obj_STOMP = null;
		protected $m_obj_RestCon = null;

		public function __construct($str_LockPath, $arr_Options = array())
		{
			$this->set_LockPath($str_LockPath);
			$this->set_Name(self::C_STR_NAME);
			$this->m_arr_Threads = array();
			$this->arr_Options = $arr_Options;
			parent::__construct();
			$this->set_MaxThreads(self::C_INT_PULL_THREADS);
		}

		protected function get_RestCon()
		{
			if (!$this->m_obj_RestCon)
			{
				$this->m_obj_RestCon = new cRestConnector("");
				$this->m_obj_RestCon->set_Login(cConfig::C_STR_AMPLE_SILO_USER_NAME, cConfig::C_STR_AMPLE_SILO_PASSWORD);
			}

			return $this->m_obj_RestCon;
		}

		protected function get_STOMP()
		{
			if (!$this->m_obj_STOMP)
			{
				$this->m_obj_STOMP = new \cStomp();
				$this->m_obj_STOMP->subscribe(\cStomp::C_STR_QUEUE_AH_NEW);
			}

			return $this->m_obj_STOMP;
		}

		public function run($bool_Force = false)
		{
			//print("Test".__LINE__."\n");
			$this->set_Force($bool_Force);
			if (!parent::run())
			{
				return false;
			}

			$this->startThreads();
			$this->wait4Threads();

			return true;
		}

		private function startThreads()
		{
			while (sizeof($this->m_arr_Threads) <= $this->get_MaxThreads()) 
			{
				$this->killDeadThreads();
				if (!$this->startThread())
				{
					break;
				}

				//print(sizeof($this->m_arr_Threads) . " Threads currently running." . PHP_EOL);
			}
		}

		private function startThread()
		{
			$obj_STOMP = $this->get_STOMP();

			$obj_Msg = $obj_STOMP->getMessage();

			if (!$obj_Msg)
			{
				return false;
			}

			$str_ID = $obj_Msg->body;

			$str_Command = __FILE__ . " -c --id=\"" . $str_ID . "\"";
			//print($str_Command . "\n");
			$int_I = sizeof($this->m_arr_Threads);
			$this->m_arr_Threads[$int_I] = \cThread::Create($str_Command, code\cConfig::C_STR_PATH_PHP);

			$obj_STOMP->ackMessage($obj_Msg);

			return true;
		}

		private function killDeadThreads()
		{
			foreach ($this->m_arr_Threads as $str_Key => $obj_Thread)
			{
				if (!$obj_Thread->isActive())
				{
					$str_Return = $obj_Thread->listen();
					print($str_Return);
					$obj_Thread->close();
					unset($this->m_arr_Threads[$str_Key]);
				}
			}
		}

		private function wait4Threads()
		{
			while (sizeof($this->m_arr_Threads) > 0)
			{ //No Items to process
				$this->killDeadThreads();
				$this->startThreads();
			}
		}

		public function runChunk()
		{
			$str_ID = $this->arr_Options["id"];
			$obj_AH_Doc = null;
			$arr_Data = array();
			$obj_RestCon = $this->get_RestCon();
			$obj_RestCon->set_Url(cRestServices::get_AHDataService($str_ID));

			$str_Contents = $obj_RestCon->send_Get();

			$obj_RestCon->clear_Params();

			//$obj_Date = new \DateTime();

			try
			{
				$obj_AH_Doc = json_decode($str_Contents);
			}
			catch (Exception $e)
			{
				$this->set_Valid($str_ID, false);
				$this->send2ErrorQueue($str_ID);
				$this->log_Error($str_ID . " the following problem unserializeing " . $e);
				return;
			}

			if (!$this->validate_Json($obj_AH_Doc, $str_ID))
			{
				$this->set_Valid($str_ID, false);
				$this->send2ErrorQueue($str_ID);
				return;
			}

			if ($str_ID != $obj_AH_Doc->id)
			{
				$this->log_Error($str_ID . " has a missmatching id in the Json object (" . $obj_AH_Doc->id . ")");
				$this->set_Valid($str_ID, false);
				$this->send2ErrorQueue($str_ID);
				return;
			}

			$arr_Data["id"] = $obj_AH_Doc->id;
			$obj_RestCon->set_Param("id", $obj_AH_Doc->id);

			if (isset($obj_AH_Doc->harvestDate))
			{
				$obj_RestCon->set_Param("harvestDate", $obj_AH_Doc->harvestDate);
				//$arr_Data["harvestDate"] = $obj_AH_Doc->harvestDate;
			}

			if (isset($obj_AH_Doc->origId))
			{
				$obj_RestCon->set_Param("origId", $obj_AH_Doc->origId);
				//$arr_Data["origId"] = $obj_AH_Doc->origId;
			}

			if (isset($obj_AH_Doc->page))
			{
				$obj_RestCon->set_Param("page", $obj_AH_Doc->page);
				//$arr_Data["page"] = $obj_AH_Doc->page;
			}

			if (isset($obj_AH_Doc->source))
			{
				$obj_RestCon->set_Param("source", $obj_AH_Doc->source);
				//$arr_Data["source"] = $obj_AH_Doc->source;
			}

			if (isset($obj_AH_Doc->category))
			{
				$obj_RestCon->set_Param("category", $obj_AH_Doc->category);
				//$arr_Data["category"] = $obj_AH_Doc->category;
			}

			if (isset($obj_AH_Doc->client))
			{
				$obj_RestCon->set_Param("client", $obj_AH_Doc->client);
				//$arr_Data["client"] = $obj_AH_Doc->client;
			}

			//$arr_Data["date"] = $obj_Date->format("c");

			$obj_STOMP = $this->get_STOMP();

			$obj_STOMP->send(\cStomp::get_SolrIndexQueue($obj_AH_Doc->client), $str_ID);

			$obj_RestCon->set_Url(cRestServices::get_AHProperties());
			$obj_RestCon->send_Put();
			//cRestServices::send_Put(cRestServices::get_AHProperties(), $arr_Data);

			$this->set_Valid($str_ID, true);

		}
		
		private function send2ErrorQueue($str_ID)
		{
			$obj_STOMP = $this->get_STOMP();

			$obj_STOMP->send(\cStomp::C_STR_QUEUE_AH_ERROR, $str_ID);
		}

		private function set_Valid($str_ID, $bool_Valid = true)
		{
			$obj_RestCon = $this->get_RestCon();
			$obj_RestCon->set_Url(cRestServices::get_AHValid($str_ID));
			$obj_RestCon->clear_Params();

			$obj_RestCon->set_Param("valid", $bool_Valid);
			$obj_RestCon->set_Param("id", $str_ID);
			$obj_RestCon->send_Put();
			//cRestServices::send_Put(cRestServices::get_AHValid($str_ID), $arr_Data);
		}

		private function validate_Json($obj_Json, $str_ID = "unknown")
		{
			$str_SchemaLoc = dirname(dirname(dirname(dirname(__FILE__)))) . "/validation/json/";
			$str_Schema = file_get_contents($str_SchemaLoc . "AmpleHarvest.json");
			\cJsonValidator::add_Path($str_SchemaLoc);

			$int_Return = \cJsonValidator::validate($obj_Json, $str_Schema);
			if ($int_Return < 0)
			{

				$this->log_Error($str_ID . " had the following error parsing the json " . \cJsonValidator::convert_ErrorCode($int_Return) .
					"\n Schema Location - " . \cJsonValidator::get_LastSchemaPos() .
					"\n Json Location - " . \cJsonValidator::get_LastJsonPos() .
					"\n Error Text - " . \cJsonValidator::get_ErrorText());

				return false;
			}
			return true;
		}

	}

	if (isset($arr_Options["c"]))
	{
		$obj_Task = new process_Data_Queue(null, $arr_Options);
		$obj_Task->runChunk();
	}
